<?php
// +----------------------------------------------------------------------
// | UCToo [ Universal Convergence Technology ]
// +----------------------------------------------------------------------
// | Copyright (c) 2014-2021 https://www.uctoo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: UCToo <contact@uctoo.com>
// +----------------------------------------------------------------------

declare (strict_types = 1);

namespace catcher\command\Tools;

use catcher\CatchAdmin;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use QL\QueryList;
use think\facade\Log;
use uctoo\library\JsParser as utilJsParser;
use uctoo\util\library\BeautifyHtml;
use Peast\Peast;

/**
 * 生成CRUD页面
 *
 * Class CompressPackageCommand
 * @package catcher\command\Tools
 */
class CreateElmformCommand extends Command
{
    protected $table;

    protected function configure()
    {
        // 指令配置
        $this->setName('create:elmform')
            ->addArgument('table', Argument::REQUIRED, 'create pages')                             //codelabs.data_source字段
            ->addOption('configjson', '-c', Option::VALUE_OPTIONAL, 'config json data')  //codelabs.config_data字段
            ->addOption('inputjson', '-i', Option::VALUE_OPTIONAL, 'input json')          //codelabs.input字段
            ->addOption('outputjson', '-o', Option::VALUE_OPTIONAL, 'output json')         //codelabs.output字段
            ->addOption('datastructure', '-d', Option::VALUE_OPTIONAL, 'datastructure json')  //codelabs.data_structure字段
            ->addOption('templatefilename', '-t', Option::VALUE_OPTIONAL, 'template filename') //codelabs.template_filename字段
            ->addOption('templatecode', '-e', Option::VALUE_OPTIONAL, 'template code')     //codelabs.template_code字段
            ->addOption('saveoutputauth', '-a', Option::VALUE_OPTIONAL, 'can save output file')
            ->setDescription('Just for catchAdmin create element UI pages');
    }

    protected function execute(Input $input, Output $output)
    {
        $table = $input->getArgument('table');
        $configjson = $input->getOption('configjson');
        $inputjson = $input->getOption('inputjson');
        $outputjson = $input->getOption('outputjson');
        $datastructure = $input->getOption('datastructure');
        $templatefilename = $input->getOption('templatefilename');
        $templatecode = $input->getOption('templatecode');
        $saveoutputauth = $input->getOption('saveoutputauth');
        //输出配置
        //用户模板配置
        $configArray = json_decode($configjson,true);
        $inputArray = json_decode($inputjson,true);
        $outputArray = json_decode($outputjson,true);
        $datastructureArray = json_decode($datastructure,true);          //在UCToo table template中，数据结构仅用来生成模板配置初始化，并未在create:elmform命令中用于生成代码

        //controller url
        $class = $inputArray['controller'];
        $class = explode('\\', $class);
        $controllerName = lcfirst(array_pop($class));
        try{
            //加载crud页面模板
            if($templatecode){
                $stub = $templatecode;
            }elseif($templatefilename){
                $stub = file_get_contents(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR .'elm' . DIRECTORY_SEPARATOR . $templatefilename);
            }
            //加载router.js模板
            $routerjsstub = file_get_contents(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR .'elm' . DIRECTORY_SEPARATOR . 'routerjs.stub');
            //用QueryList处理模板,会自动把自闭合标签都处理成闭合标签，例如<input />输出成<input></input>，对功能没影响
            //由于QueryList无法处理 @click、@close等@开头的标签事件，因此模板中所有@都用el-event-at_ 人工替换了
            $ql = QueryList::html($stub);
            //循环所有字段,组装queryParam
            $queryParamHtml = '';
            $dropdownItemHtml = '';
            $tableColumnHtml = '';
            $formItemHtml = '';
            $replaceFields = '';

            foreach($configArray as $k => $v){
                $tempScript = $ql->find('script');              //table模板中的script段
                // 获取第一个el-form-item元素,用于组装组装queryParam,第一个搜索el-form和第二个编辑el-form算法一致仅参数不同
                $queryParamNode = $ql->find('el-form:eq(0) el-form-item:eq(0)');
                $queryParamNode->attr('prop',$v['field']);
                $queryParamNode->attr('label',$v['comment']);
                $queryParamInputNode = $ql->find('el-form:eq(0) el-form-item:eq(0) el-input:eq(0)');
                $queryParamInputNode->attr('v-model','queryParam.'.$v['field']);
                $queryParamInputNode->attr('placeholder',$v['comment']);
                $queryParamInputNode->attr('type',$v['inputType']);//兼容用户配置了textarea控件类型
                $queryParamHtml = $queryParamHtml.$queryParamNode->htmlOuter();
                // 获取第一个el-checkbox-group元素,用于组装el-dropdown-item
                $dropdownItemNode = $ql->find('el-checkbox-group:eq(0) el-dropdown-item:eq(0)');
                $dropdownItemCheckNode = $ql->find('el-checkbox-group:eq(0) el-dropdown-item:eq(0) el-checkbox');
                $dropdownItemCheckNode->attr('label',$v['field']);
                $dropdownItemHtml = $dropdownItemHtml.$dropdownItemNode->htmlOuter();
                // 获取第二个el-table-column元素,用于组装el-table-column
                $tableColumnNode = $ql->find('el-table-column:eq(1)');
                $tableColumnNode->attr('prop',$v['field']);
                $tableColumnNode->attr('label',$v['comment']);
                if(!$v['sortable']){
                    $tableColumnNode->removeAttr('sortable');
                }
                $tableColumnHtml = $tableColumnHtml.$tableColumnNode->htmlOuter();
                // 获取第二个el-form-item元素,用于组装el-form-item
                $formItemNode = $ql->find('el-form:eq(1) el-form-item:eq(0)');
                $formItemNode->attr('prop',$v['field']);
                $formItemNode->attr('label',$v['comment']);
                $formItemInputNode = $formItemNode->children();
                switch ($v['inputType']) {               //根据控件类型合并控件代码
                    case 'input':
                    case 'datepicker':
                    case 'switch':
                        $componentCode = $v['component_code'];
                        $qlc = QueryList::html($componentCode);
                        $ItemInputNode = $qlc->find('template');         //控件模板中的template段
                        $formItemInputNode->replaceWith($ItemInputNode->htmlOuter());
                        //控件桩模板中没有script段，就到此为止了
                        break;
                    case 'select':
                    case 'upload':
                    case 'chinaareadata':
                        $componentCode = $v['component_code'];
                        $qlc = QueryList::html($componentCode);
                        $ItemInputNode = $qlc->find('template');         //控件模板中的template段
                        $formItemInputNode->replaceWith($ItemInputNode->htmlOuter());
                        $ItemInputJs = $qlc->find('script');            //控件模板中的script段
                        $jsmerge = utilJsParser::js_merge($tempScript->html(),$ItemInputJs->html());   //合并控件js代码到模板js代码段
                        $tempScript->replaceWith('<script>'.$jsmerge.'</script>');
                        break;
                }

                $formItemHtml = $formItemHtml.$formItemNode->htmlOuter();
                $replaceFields = $replaceFields.$v['field'].":'',";
            }
            //组装的queryParamHtml替换模板中的queryParam,
            $ql->find('el-form:eq(0) el-form-item:eq(0)')->replaceWith($queryParamHtml);
            //组装的dropdownItemHtml替换模板中的dropdownItem,
            $ql->find('el-checkbox-group:eq(0) el-dropdown-item:eq(0)')->replaceWith($dropdownItemHtml);
            //组装的tableColumnHtml替换模板中的tableColumn,
            $ql->find('el-table-column:eq(1)')->replaceWith($tableColumnHtml);
            //组装的formItemHtml替换模板中的formItem,
            $ql->find('el-form:eq(1) el-form-item:eq(0)')->replaceWith($formItemHtml);

            $html = $ql->getHtml();
            //el-event-at_ 替换回 @
            $html = str_replace("el-event-at_","@",$html);

            //替换表格字段
            $html = str_replace("el_js_replace_fields:''",$replaceFields,$html);         //带不带空格都替换一遍
            //替换表格字段
            $html = str_replace("el_js_replace_fields: ''",$replaceFields,$html);        //todo：这里极其迷惑,由于之前的操作会将模板中的符合js语法的占位符el_js_replace_fields:''处理成加了空格的结果，需要找一种更好的占位符方案
            //替换url
            $html = str_replace("el-js-replace-url",$controllerName,$html);
            //替换表格名
            $html = str_replace("el-js-replace-formName",$table,$html);
            //替换模块名
            $html = str_replace("el-js-replace-module",$outputArray['module'],$html);

            //替换routerjs.stub中的变量
            $routerjs = str_replace("vue-replace-module",$outputArray['module'],$routerjsstub);
            $routerjs = str_replace("vue-replace-path",$outputArray['path'],$routerjs);
            $routerjs = str_replace("vue-replace-filename",$outputArray['filename'],$routerjs);
            $routerjs = str_replace("vue-replace-controller",$controllerName,$routerjs);
            //保存crud页面
            //Log::write($pathArray,'debug');

            if($outputArray['module'] && $outputArray['path'] && $outputArray['filename'] && $saveoutputauth){
                file_put_contents(CatchAdmin::moduleViewDirectory($outputArray['module'],$outputArray['path']) . $outputArray['filename'] .'.vue', $html);
            }
            //保存router.js
            //file_put_contents(CatchAdmin::moduleRouterjsDirectory($module) . 'router' .'.js', $routerjs);
        }catch (\Throwable $e) {
            $output->error($e->getMessage(). ': Error happens at ' .$e->getFile() .  ' '. $e->getLine() . '行');
        }
        //reformat code 格式化
        $beautify = new BeautifyHtml(array(
            'indent_inner_html' => false,
            'indent_char' => " ",
            'indent_size' => 2,
            'wrap_line_length' => 32786,
            'unformatted' => ['code', 'pre'],
            'preserve_newlines' => false,
            'max_preserve_newlines' => 32786,
            'indent_scripts'	=> 'normal', // keep|separate|normal
        ));
        $html = $beautify->beautify($html);
        $output->writeln($html);
    }

}

